package com.zy.kotlinbaselibrary.log

import android.text.TextUtils
import org.json.JSONArray
import org.json.JSONObject
import java.io.PrintWriter
import java.io.StringReader
import java.io.StringWriter
import java.net.UnknownHostException
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource


object LogFormat {

    private const val JSON_INDENT = 4
    private const val XML_INDENT = 4

    private const val VERTICAL_BORDER_CHAR = '║'

    // Length: 100.
    private const val TOP_HORIZONTAL_BORDER =
        "╔═════════════════════════════════════════════════" + "══════════════════════════════════════════════════"

    // Length: 99.
    private const val DIVIDER_HORIZONTAL_BORDER =
        "╟─────────────────────────────────────────────────" + "──────────────────────────────────────────────────"

    // Length: 100.
    private const val BOTTOM_HORIZONTAL_BORDER =
        "╚═════════════════════════════════════════════════" + "══════════════════════════════════════════════════"

    fun formatJson(json: String?): String? {

        var formatted: String? = json

        try {
            json?.let {
                if (it.startsWith("{")) {
                    val jo = JSONObject(json)
                    formatted = jo.toString(JSON_INDENT)
                } else if (it.startsWith("[")) {
                    val ja = JSONArray(json)
                    formatted = ja.toString(JSON_INDENT)
                }
            }

        } catch (e: Exception) {
            e.printStackTrace()
        }


        return formatted
    }

    fun formatXml(xml: String?): String? {
        var formatted: String? = null
        if(TextUtils.isEmpty(xml)){
            return formatted
        }
        try {
            val xmlInput = StreamSource(StringReader(xml))
            val xmlOutput = StreamResult(StringWriter())
            val transformer = TransformerFactory.newInstance().newTransformer()
            transformer.setOutputProperty(OutputKeys.INDENT, "yes")
            transformer.setOutputProperty(
                "{http://xml.apache.org/xslt}indent-amount",
                XML_INDENT.toString()
            )
            transformer.transform(xmlInput, xmlOutput)
            formatted = xmlOutput.writer.toString().replaceFirst(">".toRegex(), ">" + XPrinter.lineSeparator)
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return formatted
    }

    fun formatThrowable(tr: Throwable?): String {


        if (tr == null) {
            return ""
        }
        var t = tr
        while (t != null) {

            if (t is UnknownHostException) {
                return ""
            }

            t = t.cause
    }

        val sw = StringWriter()
        val pw = PrintWriter(sw)
        tr.printStackTrace(pw)
        pw.flush()
        return sw.toString()
    }


    fun formatArgs(format: String, vararg args: Any): String {

        try {
            if (!TextUtils.isEmpty(format)) {
                return String.format(format, *args)
            }

        } catch (e: Exception) {
        }

        val sb = StringBuilder()
        var i = 0
        val N = args.size
        while (i < N) {
            if (i != 0) {
                sb.append(", ")
            }
            sb.append(args[i])
            i++
        }
        return sb.toString()

    }

    fun formatBorder(segments: Array<String>?): String {
        if (segments == null || segments.isEmpty()) {
            return ""
        }

        val nonNullSegments = ArrayList<String>()


        var nonNullCount = 0


        for (segment in segments) {
//            nonNullSegments[nonNullCount++] = segment
//            nonNullSegments.plus(segment)

            nonNullSegments.add(segment)
            nonNullCount ++
        }
        if (nonNullCount == 0) {
            return ""
        }

        val msgBuilder = StringBuilder()
        msgBuilder.append(TOP_HORIZONTAL_BORDER).append(XPrinter.lineSeparator)
        for (i in 0 until nonNullCount) {
            msgBuilder.append(appendVerticalBorder(nonNullSegments[i]))
            if (i != nonNullCount - 1) {
                msgBuilder.append(XPrinter.lineSeparator).append(DIVIDER_HORIZONTAL_BORDER)
                    .append(XPrinter.lineSeparator)
            } else {
                msgBuilder.append(XPrinter.lineSeparator).append(BOTTOM_HORIZONTAL_BORDER)
            }
        }
        return msgBuilder.toString()
    }

    private fun appendVerticalBorder(msg: String): String {
        val borderedMsgBuilder = StringBuilder(msg.length + 10)
        val lines = msg.split(XPrinter.lineSeparator.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
        var i = 0
        val N = lines.size
        while (i < N) {
            if (i != 0) {
                borderedMsgBuilder.append(XPrinter.lineSeparator)
            }
            val line = lines[i]
            borderedMsgBuilder/*.append(VERTICAL_BORDER_CHAR)*/.append("  ").append(line)
            i++
        }
        return borderedMsgBuilder.toString()
    }
}
